package kr.hkit.xmlhandler.dom;

import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class DomEx {
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(DomEx.class);

	public static void main(String[] args) {
		DomEx domParser = new DomEx();
		String xmlFilePath = "personList.xml";
		
		try {
			Document domObj = domParser.parse(xmlFilePath);
			if (domObj != null) {
				logger.debug("Parsing success");	
			}else{
				logger.debug("Parsing error");
			}
			
/*			domParser.printTagValue(domObj, "list");
			domParser.printTagValue(domObj, "person");
			domParser.printTagValue(domObj, "name");
			domParser.printTagValue(domObj, "company");
			
			domParser.printAttrValue(domObj, "list");
			domParser.printAttrValue(domObj, "person");
			domParser.printAttrValue(domObj, "name");
			domParser.printAttrValue(domObj, "company");
			
			System.out.println();*/
			domParser.printValue(domObj);
		} catch (Exception e) {
			if (logger.isDebugEnabled()) {
				logger.debug("main(String[]) - DOM Parser error", e);
			}
		}
	}
	
	public void printValue(Document doc){
		Element root = doc.getDocumentElement();
		
		StringBuilder sb = new StringBuilder("\nRoot Element \n");
		sb.append("\t getTagName(): " + root.getTagName()+"\n");
		sb.append("\t getNodeName(): " + root.getNodeName()+ "\n");
		sb.append("\t getNodeValue() :"+ root.getNodeValue() +"\n");
		sb.append("\t getLocalName():" + root.getLocalName() + "\n");
		sb.append("\t getNodeName():" + root.getNodeName()+ "\n");
		
		sb.append("\t hasAttributes():" + root.hasAttributes()+ "\n");
		sb.append("\t hasChildNodes():" + root.hasChildNodes()+ "\n");
		
		logger.debug(sb);
		
		if (!root.hasChildNodes())return;
		
		NodeList nodeList = root.getChildNodes();
		int nodeListLen = nodeList.getLength();
		System.out.println("childnode 개수: " + nodeListLen);
		for(int i=0; i<nodeListLen; i++){
			Node childNode = nodeList.item(i);
			if (childNode.getNodeName().equals("person"))
				printNodeInfo(childNode);
		}
	}
	
	public void printNodeInfo(Node node){
		StringBuilder sb = new StringBuilder("\n\t\t getNodeName() : "+node.getNodeName().trim()+"\n");
		sb.append("\t\t getNodeType() : "+ node.getNodeType()+"\n");
		sb.append("\t\t getNodeValue() : "+ node.getNodeValue()+"\n");
		sb.append("\t\t hasChildNodes() : "+ node.hasChildNodes()+"\n");
		sb.append("\t\t hasAttributes() : "+ node.hasAttributes()+"\n");
		
		if (logger.isDebugEnabled()) {
			logger.debug("printNodeInfo(Node) - " + sb);
		}
		
		if (node.hasAttributes()){
			NamedNodeMap mnMap = node.getAttributes();
			for(int i=0; i<mnMap.getLength(); i++){
				Node attrNode = mnMap.item(i);
				logger.debug("Attr name : " + attrNode.getNodeName() + " Attr value : " + attrNode.getNodeValue());
			}
		}
		
		if (node.hasChildNodes()){
			NodeList childNodes = node.getChildNodes();
			for(int i=0; i<childNodes.getLength(); i++){
				printNodeInfo(childNodes.item(i));
			}
		}
	}
	
	public void printAttrValue(Document doc, String tagName){
		NodeList nodeList = doc.getElementsByTagName(tagName);
		/*getElementsByTagName 메서드는 null객체를 반환하지 않음*/
		if (nodeList.getLength()==0){
			logger.debug("No matched node [" + tagName + "]");
			return;
		}
		for(int i=0; i<nodeList.getLength(); i++){
			NamedNodeMap attrMap = nodeList.item(i).getAttributes();
			int attrLen = attrMap.getLength();
			if (attrLen == 0) continue;
			for (int j=0; j < attrLen; j++){
				Node node = attrMap.item(j);
				logger.debug("Attr name : " + node.getNodeName() + " Attr value : " + node.getNodeValue());
			}
		}
	}
	
	public void printTagValue(Document doc, String tagName){
		
		NodeList nodeList = doc.getElementsByTagName(tagName);
		/*getElementsByTagName 메서드는 null객체를 반환하지 않음*/
		if (nodeList.getLength()==0){
			logger.debug("No matched node [" + tagName + "]");
			return;
		}
		
		//tagName 매개변수와 매칭되는 노드들이 있으면 반복문을 돌며 값을 출력
		for(int i=0; i<nodeList.getLength(); i++){
			/*Node valueNode = nodeList.item(i).getFirstChild();*/
			Node valueNode = nodeList.item(i).getChildNodes().item(0);

			if (valueNode.getNodeType() != Node.TEXT_NODE && valueNode.getNodeType() != Node.CDATA_SECTION_NODE) continue;
			 
			String value = valueNode.getNodeValue();
			if (value != null) value = value.trim();
			
			logger.debug("Tag name : " + tagName + ", value : " + value);
		}
	}

	public Document parse(String path) throws Exception{
		Document rtObj = null;
		
		if (path == null || "".equals(path))
			throw new IllegalArgumentException("Parameter should not be null");
		
		File xmlFile = new File(path);
		if (!(xmlFile.exists() && xmlFile.isFile()))
			throw new IllegalArgumentException("Wrong parameter");
		
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		rtObj = builder.parse(xmlFile);
		
		return rtObj;
	}
}
